﻿/**
 * @Author Lion Shooray 2007-7-28 iTruschina. Co.,Ltd
 * @Version 2.5
 *
 * English translation by Wang Wei 2008-01-05
 */

 /**
  * InstallCert: Install Certificate issued by CA
  * @param certChain(mandatory) : P7 string, Based64 encoded, including user certificate and certificate chain
  */
function InstallCert(certChain) {
	try {
		cenroll.DeleteRequestCert = false;
		cenroll.WriteCertToCSP = true;
		cenroll.acceptPKCS7(certChain);
		return true;
	} catch(e) {
		if(-2147023673 == e.number) {
			alert("Certificate install canceld by user! \n If you want to install the certificate later, please click 'Install Digital Certificate' button");
			return false;
		} else {
			alert("Install certificate error!\nError No.: " + e.number + "\nError Description: " + e.description);
			return false;
		}
	}
}

/**
 * installCAChain 安装CA证书链
 * @param cACertSignBufP7(mandatory) PKCS7格式证书链
 */
function installCAChain(cACertSignBufP7) {
    try{
         //cenroll.InstallPKCS7(cACertSignBufP7);acceptPKCS7
    	cenroll.acceptPKCS7(cACertSignBufP7);
    } catch(e) {
    	alert(e.description);
        if(-2147023673 == e.number) {
            return false;
        } else {
            alert("安装证书链时发生错误！\n错误原因：" + e.description + "\n错误代码：" + toHex(e.number));
        }
    }
}


function installCertKmc(certSign, certKmc, kmcReq1, kmcReq2, kmcReq3, kmcRep1, kmcRep2, kmcRep3) {
	if( certKmc.length < 1 )
			certKmc = kmcRep2;

	var kmcRep1Arr = kmcRep1.split("&amp;");
	var kmcRep1Map = {};
	for(i = 0 ; i < kmcRep1Arr.length ; i++){
			var nv = kmcRep1Arr[i].split("=");
			kmcRep1Map[nv[0]] = URLDecode(nv[1]);
//			alert(nv[0] + "\n" + nv[1] + "\n" + kmcRep1Map[nv[0]]);
	}
	try {
		cenroll.DeleteRequestCert = false;
		cenroll.WriteCertToCSP = true;
		var ret = cenroll.acceptSeal(
						certSign,
						kmcRep1Map["userSeal"],
						certKmc,
						kmcRep1Map["encPrivateKeyUser"],
						kmcRep1Map["userCipher"],
						kmcRep1Map["userIV"]
						);
		return true;
} catch (e) {
    if(e.Number!= -2146893792)
			alert("安装证书发生错误！\n错误号: " + e.number + "\n错误描述: " + e.description);
			return false;
	}
}

function URLDecode(psEncodeString) {
    // Create a regular expression to search all +s in the string
    var lsRegExp = /\+/g;
    // Return the decoded string
    return unescape(String(psEncodeString).replace(lsRegExp, " "));
}


/**
 * installCAChain Install CA Cert. Chain
 * @param cACertSignBufP7(mandatory) Cert. Chain in PKCS7 formmat
 */
// function installCAChain(cACertSignBufP7) {
//    try{
//         cenroll.InstallPKCS7(cACertSignBufP7);
//    } catch(e) {
//        if(-2147023673 == e.number) {
//            return false;
//        } else {
//			alert("Install certificate error! \nError Description" + e.description + "\nError No.：" + toHex(e.number));
//        }
//    }
//}

 /**
 * findProviders : Crypto Service Provider(CSP) enumerated on local machine, will be listed in specified <select> HTML element
 * @param objProviderList(mandatory) : CSP list, an <select> HTML element, as described in above line 
 * @param defaultProvider(optional) : default CSP
 * @param allowedProviders(optional) : allowec CSP ,an Array
 */
function findProviders(objProviderList, defaultProvider, allowedProviders) {
	if(typeof(defaultProvider) == "undefined" || defaultProvider == "")
		defaultProvider = "EnterSafe ePass3003 CSP v1.0";
	var i = 0; nIndex = 0;
	var providerType = 1;//The default value for this property is 1
	var maxProviderType = 1; //max is 24
	
	var providerName;
	while(providerType <= maxProviderType) {
		i = 0; //从0开始枚举
		cenroll.ProviderType = providerType;
		while(true) {
			try {
				providerName = cenroll.enumProviders(i, 0);
				if(providerName == "" || providerName == null) {
					break;
				}
			} catch(e) {
				break;
			}
			if(providerName.length == 0) {
				break;
			} else {
				var el = document.createElement("option");
				el.text = providerName;
				el.value = providerType;
				
				if(typeof(allowedProviders) == "string") {
					if(providerName == allowedProviders) {
						objProviderList.add(el);
						nIndex++; //总索引
					}
				} else if(typeof(allowedProviders) == "object" && allowedProviders.length > 0) {
					for(var j = 0; j < allowedProviders.length; j++){
						if(providerName == allowedProviders[j]) {
							objProviderList.add(el);
							nIndex++; //总索引
						}
					}
				} else { //typeof(allowedProviders)=="undefined" || allowedProviders == ""
					objProviderList.add(el);
					nIndex++; //总索引
				}
				
				if(providerName == defaultProvider)
					objProviderList.selectedIndex = nIndex - 1;
				i++;
			}
		}
		providerType++;
	}
	if(objProviderList.length == 0){
		var defaultOption = document.createElement("option");
		defaultOption.text = "Specified USB Key driver is not installed.";
		defaultOption.value = "";
		objProviderList.add(defaultOption);
	}
}

/**
 * genEnrollCSR : Apply for Cert. , create key-pair and generate CSR (Certificate Signing Request)
 * @param objProviderList(mandatory) : CSP list, <select> HTML element
 * @param cryptFlag(optional)
 *		0x0 : means that the private-key can NOT be exported, but strong private-key protection are not required
 *		0x1 : means that the private-key can be exported, this is the default value
 *		0x2 : strong private-key protection
 *		0x3(0x1|0x2) private-key can be exported and strong private-key protection are also required
 */
function genEnrollCSR(objProviderList, cryptFlag) {
    var selectedItem = objProviderList.item(objProviderList.selectedIndex);
	return genKeyAndCSR(selectedItem.text, selectedItem.value, cryptFlag);
}

/**
 * genRenewCSR : Update Cert. and generate CSR for the updating
 * @param objProviderList(mandatory) : CSP list, <select> HTML element
 * @param cryptFlag(mandatory)
 *		0x0 : means that the private-key can NOT be exported, but strong private-key protection are not required
 *		0x1 : means that the private-key can be exported, this is the default value
 *		0x2 : strong private-key protection
 *		0x3(0x1|0x2) private-key can be exported and strong private-key protection are also required
 * @param objOldCert(mandatory) : Cert. Object to be updated（PTALib.Certificate）
 */
function genRenewCSR(objProviderList, cryptFlag, objOldCert) {
	var oldCertCSP = objOldCert.CSP; //CSP of old certificate
	var providerName, providerType;
	
	if(typeof(objProviderList) == "string") {
		providerName = objProviderList;
		providerType = 1;
	} else if(typeof(objProviderList) == "object") {
		providerName = objProviderList.item(objProviderList.selectedIndex).text;
		providerType = objProviderList.item(objProviderList.selectedIndex).value;
	} else {
		alert("Paramter [objProviderList] is not correct.");
		return "";
	}
	
	var useOldKey = true;
	if(oldCertCSP != providerName) {
		var info = "The CSP you selected are NOT compatible with your certificate!"
			+ "\nIf you click 'OK', new key-pair will be generated for updating. If you click 'Cancel' ";

		if(!window.confirm(info)) {
			return "";
		} else
			useOldKey = false;
	}
	if(useOldKey) {
		//use old key-pair, ONLY period of validity are updated
		return genKeyAndCSR(providerName, providerType, cryptFlag, objOldCert.KeyContainer);
	} else {
		//generate new key-pair, new cert contains new key-pair and new period of validity
		return genKeyAndCSR(providerName, providerType, cryptFlag);
	}	
}

/**
 * genKeyAndCSR() : xenroll_install.js and xenroll_function.js MUST be included
 * genKeyAndCSR  : generate key-pair and return CSR
 * @param providerName(mandatory) : CSP name
 * @param providerType(mandatory) : CSP type
 * @param cryptFlag(mandatory)
 *		0x0 : means that the private-key can NOT be exported, but strong private-key protection are not required
 *		0x1 : means that the private-key can be exported, this is the default value
 *		0x2 : strong private-key protection
 *		0x3(0x1|0x2) private-key can be exported and strong private-key protection are also required
 * @param keyContainer(optional)
 *		You can use PTALib.Certificate.KeyContainer() to obtain key container of old certificate
 *		Key container name, need to be set when updating certificate. Old keys will be used for sending CSR
 *		Old certificate will be overwrited if it is stored in USB KEY
 * @return : CSR
 */
function genKeyAndCSR(providerName, providerType, cryptFlag, keyContainer) {
	try {
        cenroll.Reset(); //first,reset it
				
		cenroll.ProviderName = providerName;
		cenroll.ProviderType = providerType;
		
		var keyflags = 0;
		if(typeof(cryptFlag) != "number") {
			cryptFlag = 0x00000001; //means the private-key can be exported, this is the default value
		}
		keyflags = keyflags | cryptFlag;
		
		if(typeof(keyContainer) == "string" && keyContainer != "") {//applicable for updating Cert.
			cenroll.UseExistingKeySet = true;
			cenroll.ContainerName = keyContainer;
		}
		cenroll.HashAlgorithm = "MD5"; //SHA1
		cenroll.KeySpec = 1;
		
		var csr = "";
		cenroll.GenKeyFlags = 0x04000000 | keyflags; //1024bits
		csr = cenroll.createPKCS10("CN=itrus_enroll", "1.3.6.1.5.5.7.3.2");
		return csr.replace(/\r*\n/g, "");
	} catch(e) {
	alert(e.Source);
			var keyNotPresent = "Selected CSP can NOT provide service, maybe:"
				+ "\n1. You have not plug the USB KEY yet or the pluged USB KEY is not recognized by system."
				+ "\n2. Your USB KEY has not been initialized.";

		var keyContainerNotPresent = "Selected KeyContainer can NOT provide service. \nIf you are updating your certificate, please select the CSP of your certificate";

		if(-2147023673 == e.number //800704C7 User Canceled
		 || -2147418113 == e.number || -2146893795 == e.number //Zhong chao USB key User Canceled when input PIN
		 || -2146434962 == e.number //FT ePass2001 USB key User Canceled
		 || -2146955245 == e.number //FT ePass2001 USB key User PIN Canceled
		 ) {
			return "";
		} else if(-2146893802 == e.number) { //80090016
			if(providerName.indexOf("SafeSign") != -1)
				alert(keyNotPresent); //error will ocurr if Gieseck&Devrient's (Gi-De) KEY not pluged
			else
				alert(keyContainerNotPresent); //if KeyContainer can NOT provide service, other KEY will report this error
			return "";
		} else if(-2146893799 == e.number) {
			alert(keyNotPresent); //error will ocurr if Gieseck&Devrient's (Gi-De) KEY not pluged
			return "";
		} else if(-2146435060 == e.number //8010000C FTSafe ePass2000 will be reported if key not pluged
			|| -2146893792 == e.number //80090020 FEITIAN ePassNG  will be reported if key not pluged
			) {
			alert(keyNotPresent); //error will ocurr if Gieseck&Devrient's (Gi-De) KEY not pluged
			return "";
		} else {
			//Report error to user if there is an error ocurred during creating 1024-bits key-pair or creating CSR
			alert("An error ocurred during applying certificate!\nError Descripton:" + e.description + "\nError No.：" + e.number);
			return "";
		}
	}
}

/**
 * IsValidBrowser : Check out that if the user-agent is Microsofte IE browser
 * @return true if it is IE else false*/
function IsValidBrowser() {
	var iePos = navigator.userAgent.indexOf("MSIE");
	if(iePos == -1) {
		//NOT IE
		return false;
	} else {
		var endStr = navigator.userAgent.substring(iePos + 4, navigator.userAgent.length);
		var ieVersion = parseInt(endStr);
		//alert("IE Version = " + ieVersion);
		if(ieVersion < 4) {
			return false;
		} else {
			return true;
		}
	}
}